#include "StdAfx.h"
#include "M2Info.h"
#include "M2InfoCache.h"
#include "M2InstanceLoader.h"
#include "M2BatchRender.h"
#include "M2VideoLoadTask.h"
#include "M2Manager.h"

M2Manager* Singleton<M2Manager>::m_instance = NULL;

M2Manager::M2Manager() : mShader(sShaderMgr.getShader("M2INSTANCESHADER.FX")) {
	new M2InfoCache();
}

ui32 M2Manager::addInstance(const std::string& modelName, MDDF df) {
	renderLock.Acquire();
	float rotX = Math::PI * df.rotation[0] / 180.0f;
	float rotY = Math::PI * df.rotation[1] / 180.0f;
	float rotZ = Math::PI * df.rotation[2] / 180.0f;

	auto rndr = mBatches.find(modelName);
	if(rndr != mBatches.end()) {
		ui32 ret = rndr->second->addInstance(df.position[0], df.position[1], df.position[2], df.scaleFactor / 1024.0f, 
			rotX, rotY, rotZ);
		renderLock.Release();
		return ret;
	}

	renderLock.Release();
	M2BatchRender* rdr = new M2BatchRender(modelName);
	ui32 ret = rdr->addInstance(df.position[0], df.position[1], df.position[2], df.scaleFactor / 1024.0f, 
		rotX, rotY, rotZ);
	renderLock.Acquire();
	mBatches[modelName] = rdr;
	renderLock.Release();
	return ret;
}

void M2Manager::render() {
	MUTEX_LOCK(renderLock);
	auto view = sCamera.GetMatView();
	auto proj = sD3D.GetMatProj();
	D3DXMATRIX matViewProj;
	D3DXMatrixMultiply(&matViewProj, &view, &proj);
	mShader.setValue("matrixViewProj", matViewProj);
	mShader.setValue("CameraPosition", sCamera.GetCamPosition());

	auto itr = mBatches.begin();
	for( ; itr != mBatches.end(); ++itr)
		itr->second->renderInstance();
}

void M2Manager::removeInstance(const std::string& modelName, ui32 id) {
	MUTEX_LOCK(renderLock);
	auto rndr = mBatches.find(modelName);
	if(rndr == mBatches.end())
		return;

	if(rndr->second->removeInstance(id)) {
		delete rndr->second;
		mBatches.erase(rndr);
	}
}

void M2Manager::changeInstancePosition(const std::string& modelName, ui32 id, const Vertex3F& newPos) {
	MUTEX_LOCK(renderLock);
	auto rndr = mBatches.find(modelName);
	if(rndr == mBatches.end())
		return;

	rndr->second->changeInstancePosition(id, newPos);
}
	